{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4vdFmXDcUiCw"
   },
   "source": [
    "## Route Navigation\n",
    "\n",
    "Finding a route from a starting place to a destination is one of the classic Search problems.\n",
    "In Search Exercise 1 we looked at path-finding on a square grid.\n",
    "In this exercise we will look at finding routes in a network (e.g. a transportation network),\n",
    "where we have a graph of locations and we have costs (e.g. milage or fuel cost, or ticket price)\n",
    "assigned to links between nodes.\n",
    "The aim is to find a route that goes from a given start location to a given destination location\n",
    "with the minimum total cost."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ZbpK0ZUjUiC1"
   },
   "source": [
    "### Download and import Brandon's Search module\n",
    "As in Search Exercise 2, we install and import the `bbSearch` module:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "U2s-kAMkUiC2",
    "outputId": "7febe21f-eb81-4d44-e80c-819cccc0b8e7"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n",
      "                                 Dload  Upload   Total   Spent    Left  Speed\n",
      "100 18747  100 18747    0     0  54182      0 --:--:-- --:--:-- --:--:-- 54182\n",
      "Loading bbSearch Version 2.1 (at 16:03, Wed 23 Feb)\n",
      "Last module source code edit 9pm Wednesday 16th Feb 2022\n"
     ]
    }
   ],
   "source": [
    "!mkdir -p bbmodcache\n",
    "!curl http://bb-ai.net.s3.amazonaws.com/bb-python-modules/bbSearch.py > bbmodcache/bbSearch.py\n",
    "from bbmodcache.bbSearch import SearchProblem, search"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5ACHjqUqUiC4"
   },
   "source": [
    "## Secifying a Route Nework\n",
    "Let us now specify  a route networ. We use the dictionary `LOCATIONS` to associate location names with `(x,y)` coordinates and the list `LINKS` to specify which pairs of locations are linked. We shall assume that all the links are straight roads and that the 'cost' of going along a given link is just the Euclidean distance between the locations at each end."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "lHsD5V98UiC4"
   },
   "outputs": [],
   "source": [
    "LOCATIONS = {\n",
    "    \"Holme\"       : (10,10),\n",
    "    \"Plumpton\"    : (48,52),\n",
    "    \"Plompton\"    : (55,60),\n",
    "    \"Plimpton\"    : (63,42),\n",
    "    \"Esp\"         : (87,21),\n",
    "    \"Spent\"       : (103,29),\n",
    "    \"Thrine\"      : (99,91),\n",
    "    \"Thrusk\"      : (117,130),\n",
    "    \"Frogsul\"     : (162,43),\n",
    "    \"Ballywick\"   : (150,75),\n",
    "    \"Runge\"       : (153,115),\n",
    "    \"Blubberwick\" : (100,55),\n",
    "    \"Flebwidge\"   : (117, 43),\n",
    "    \"Humbleton\"   : (172,61),\n",
    "    \"Nundruk\"     : (180,135),\n",
    "    \"Skoe\"        : (185, 103),\n",
    "    \"Uppert\"      : (10, 129),\n",
    "    \"Ebb\"         : (25, 93),\n",
    "}\n",
    "\n",
    "LINKS = [\n",
    "      (\"Holme\", \"Plimpton\"),\n",
    "      (\"Plumpton\", \"Plompton\"),\n",
    "      (\"Plumpton\", \"Plimpton\"),\n",
    "      (\"Plompton\", \"Ballywick\"),\n",
    "      (\"Ballywick\", \"Thrine\"),\n",
    "      (\"Thrine\",     \"Thrusk\"),\n",
    "      (\"Plimpton\",  \"Esp\"),\n",
    "      (\"Flebwidge\", \"Blubberwick\"),\n",
    "      (\"Flebwidge\",  \"Frogsul\"),\n",
    "      (\"Frogsul\",  \"Humbleton\"),\n",
    "      (\"Humbleton\", \"Skoe\"),\n",
    "      (\"Skoe\",  \"Nundruk\"),\n",
    "      (\"Runge\",  \"Nundruk\"),\n",
    "      (\"Thrusk\",  \"Runge\"),\n",
    "      (\"Plompton\", \"Ebb\"),\n",
    "      (\"Ebb\",      \"Uppert\"), \n",
    "      (\"Uppert\",  \"Thrine\"),\n",
    "      (\"Holme\",    \"Ebb\"),\n",
    "      (\"Esp\",    \"Spent\"),\n",
    "      (\"Spent\",  \"Flebwidge\")\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "O7VPuHfKUiC6"
   },
   "source": [
    "## Use `matplotlib` to display a map of the towns and road network\n",
    "\n",
    "The following code is not part of the search algorithm, it is just to enable you to visualise the situation, which will help you understand what the search algorithm is doing. When you run it you should see the map displayed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 357
    },
    "id": "zsKPVTc8UiC6",
    "outputId": "bb9705c7-69f8-41f9-e843-102c8ed80b87"
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 604.8x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.patches import Rectangle, Circle, Ellipse\n",
    "from math import sqrt\n",
    "\n",
    "mapwidth=210\n",
    "mapheight = 150\n",
    "dotrad = 4\n",
    "\n",
    "def add_circle_at(P, ax ):\n",
    "    x,y = P\n",
    "    ax.add_patch( Ellipse((x/mapwidth, y/mapheight),\n",
    "                          dotrad/mapwidth, dotrad/mapheight,\n",
    "                          fc=(0.2,0.7,1)) )\n",
    "\n",
    "def add_link( A, B, locations):\n",
    "    Ax, Ay = locations[A]\n",
    "    Ax /= mapwidth\n",
    "    Ay /= mapheight\n",
    "    Bx, By = locations[B]\n",
    "    Bx /= mapwidth\n",
    "    By /= mapheight\n",
    "    plt.plot( (Ax,Bx), (Ay,By), c='grey', zorder=0  )\n",
    "\n",
    "def distance( A, B, locations ):\n",
    "    Ax, Ay = locations[A]\n",
    "    Bx, By = locations[B]\n",
    "    dist = sqrt( (Ax-Bx)**2 + (Ay-By)**2 )\n",
    "    return dist\n",
    "    \n",
    "def draw_map( locations, links ):\n",
    "    fig = plt.figure(figsize=(mapwidth/25, mapheight/25)) \n",
    "    ax = fig.add_subplot()\n",
    "    ax.set_axis_off()\n",
    "    plt.plot( (0,0,1,1,0), (0,1,1,0,0), linewidth=0.2 )\n",
    "\n",
    "    for link in links:\n",
    "        A,B = link\n",
    "        add_link( A,B, locations )\n",
    "\n",
    "    for name, loc in locations.items():\n",
    "        add_circle_at( loc, ax )\n",
    "        plt.text( (loc[0]+1)/mapwidth, (loc[1]+1)/mapheight, name, fontsize=12 )\n",
    "\n",
    "    plt.show()\n",
    "    \n",
    "draw_map( LOCATIONS, LINKS )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "M0BD1UZHUiC7"
   },
   "source": [
    "## Specify the problem by defining a `RouteSearch` class\n",
    "\n",
    "We will now extend `SearchProblem` to specify the particular details of a route search problem.\n",
    "You will see that this is even easier than for the Jug Pouring Puzzle of Exercise 2.\n",
    "\n",
    "We can consider a state to simiply be the name of a location, the location where we are at;\n",
    "and the actions are just to go from that location to one of the other locations that it\n",
    "is linked to. Hence, each action can simply be identified with the destination.\n",
    "\n",
    "In this case the `successor` function is particularly simple, since the result of\n",
    "the action to go to a given destination location is just to be at that location. \n",
    "\n",
    "#### Cost function\n",
    "One thing that we have in the `RouteSearch` class, which was not in the `JugPouringPuzzle`\n",
    "clas is a `cost` function for a given state reached by a given path. As you will see below,\n",
    "this is just the sum of the distances between successive locations on the path."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "WbF-qw8ZUiC8"
   },
   "outputs": [],
   "source": [
    "class RouteSearch( SearchProblem ):\n",
    "    \n",
    "    def __init__(self, locations, links, start, goal):\n",
    "        self.locations = locations\n",
    "        self.links = links\n",
    "        self.initial_state = start\n",
    "        self.goal = goal\n",
    "        \n",
    "    def possible_actions(self, state):\n",
    "        destinations = []\n",
    "        for link in self.links:\n",
    "            if state == link[0]:\n",
    "                destinations.append(link[1])\n",
    "            if state == link[1]:\n",
    "                destinations.append(link[0])\n",
    "        return destinations\n",
    "    \n",
    "    def successor( self, state, action):\n",
    "        return action\n",
    "    \n",
    "    def goal_test(self, state):\n",
    "        return state == self.goal\n",
    "    \n",
    "    def cost(self, path, state):\n",
    "        cost = 0\n",
    "        ## Add costs (ie distances) for all the links along the path\n",
    "        for i,place in enumerate(path[:-1]): # There's no link out of the last location.\n",
    "            next_place = path[i+1]\n",
    "            cost += distance(place, next_place, self.locations)\n",
    "        return cost\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "mwS7SEgSUiC9"
   },
   "source": [
    "### Create Problem Instance\n",
    "We now create a particular probem instance using the route nework defined by the `LOCATIONS` and `LINKS` specified above and the Start and Goal locations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "te-JMFeHUiC9"
   },
   "outputs": [],
   "source": [
    "RS = RouteSearch( LOCATIONS, LINKS, \"Holme\", \"Nundruk\")    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "EDak8VUgUiC-"
   },
   "source": [
    "## Test the Search Algorithm\n",
    "Let us start by doing a breadth-first search without using the cost function.\n",
    "\n",
    "In the following call to search I am settin the optional `return_info` parameter to\n",
    "`True` and I am setting the variable `result_info` to store the information returned\n",
    "by the search:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "hXe0oxFcUiC-",
    "outputId": "4f6e4601-bd87-47b2-f5ec-888b59633531"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is the general SearchProblem parent class\n",
      "You must extend this class to encode a particular search problem.\n",
      "\n",
      "** Running Brandon's Search Algorithm **\n",
      "Strategy: mode=BF/FIFO, cost=None, heuristic=None\n",
      "Max search nodes: 1000  (max number added to queue)\n",
      "Searching (will output '.' each 1000 goal_tests)\n",
      "\n",
      ":-)) *SUCCESS* ((-:\n",
      "\n",
      "Path length = 6\n",
      "Goal state is:\n",
      "Nundruk\n",
      "The action path to the solution is:\n",
      "    Ebb\n",
      "    Uppert\n",
      "    Thrine\n",
      "    Thrusk\n",
      "    Runge\n",
      "    Nundruk\n",
      "\n",
      "\n",
      "SEARCH SPACE STATS:\n",
      "Total nodes generated          =      762  (includes start)\n",
      "Nodes tested (by goal_test)    =      313  (312 expanded + 1 goal)\n",
      "Nodes left in queue            =      449\n",
      "\n",
      "Time taken = 0.0111 seconds\n",
      "\n"
     ]
    }
   ],
   "source": [
    "result_info = search( RS, 'BF/FIFO', 1000, cost=None, loop_check=False, return_info = True )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HlfLaB0CUiC-"
   },
   "source": [
    "### Looking at the result information\n",
    "When `return_info` is true, the `search` function returns a dictionary containing full details of what search was carried out and result was obtained, as well as statistics about the search space and run-time.\n",
    "In a notebook file you can use the `display` function to get a data object printed out in a readable way.\n",
    "This may be useful for recording, comparing and tabulating results obtained when conducting search experiments.\n",
    "\n",
    "Let us look at the value of `result_info` returned by the previous call to `search`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "dpFL-sd4UiC_"
   },
   "outputs": [],
   "source": [
    "display(result_info)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5a_5UUMrUiC_"
   },
   "source": [
    "This display shows that the results dictionary consists of 3 sub-dictionaries with keys `'args'`, `'result'` and `'search_stats'`. \n",
    "We can see that the `'result'` sub-dictionary gives the _termination_condition_ (describing whether the goal was found). If the condition is `'GOAL_STATE_FOUND'` it will also give the particular `goal_state` and `path` that were found.\n",
    "\n",
    "Even though we did not use the distance-based `cost` function to guide the search, we can still use it to evaluate the cost of reaching the goal. In general, `bbSearch` allows the cost function to have both the path and goal as parameters, but for the `RouteSearch` problem we defined it just in terms of the path. Hence we can find the cost of this route solution as follows (in Python we can use an underscore symbol (`_`) in place of a variable, where we know the value will not be used):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "nhnKcuHYUiC_"
   },
   "outputs": [],
   "source": [
    "path= result_info[\"result\"][\"path\"]\n",
    "\n",
    "print(\"Cost of the path is:\", RS.cost(path, _))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "LczTw9sBUiC_"
   },
   "source": [
    "## Adding the cost function\n",
    "What happens if we use the cost function to control the search algorithm? Let us try it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 591
    },
    "id": "B3662cKfUiDA",
    "outputId": "5df81170-3c98-43af-98f2-bcdb935b3e4a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is the general SearchProblem parent class\n",
      "You must extend this class to encode a particular search problem.\n",
      "\n",
      "** Running Brandon's Search Algorithm **\n",
      "Strategy: mode=BF/FIFO, cost=cost, heuristic=None\n",
      "Max search nodes: 10000  (max number added to queue)\n",
      "Searching (will output '.' each 1000 goal_tests)\n",
      "..\n",
      ":-)) *SUCCESS* ((-:\n",
      "\n",
      "Path length = 8\n",
      "Goal state is:\n",
      "Nundruk\n",
      "Cost of reaching goal: 211.5233967687641\n",
      "The action path to the solution is:\n",
      "    Plimpton\n",
      "    Esp\n",
      "    Spent\n",
      "    Flebwidge\n",
      "    Frogsul\n",
      "    Humbleton\n",
      "    Skoe\n",
      "    Nundruk\n",
      "\n",
      "\n",
      "SEARCH SPACE STATS:\n",
      "Total nodes generated          =     5401  (includes start)\n",
      "Nodes tested (by goal_test)    =     2231  (2230 expanded + 1 goal)\n",
      "Nodes left in queue            =     3170\n",
      "\n",
      "Time taken = 0.1091 seconds\n",
      "\n"
     ]
    },
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "string"
      },
      "text/plain": [
       "'GOAL_STATE_FOUND'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "search( RS, 'BF/FIFO', 10000, cost=RS.cost, loop_check=False )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "k65Ma0qPUiDA"
   },
   "source": [
    "### Compare the cost of this solution with the previous one\n",
    "Since we gave a cost function as a parameter to this call to `search`, the algorithm will use this to constrain the way in which the search space is explored. It will always take nodes from the queue in order of least `cost` -- in other words shortest distance of the state (ie the palce) from the Start node (in this case the starting point of the route). Also, if a cost function is set and a goal is found, then the cost to that goal will automatically be printed out. You can see it above (between the goal state and the action path).\n",
    "\n",
    "Compare the distance cost of the path found in this solution (guited by cost) to the one found by the previous search (which was not guided by cost)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "nOyWDQtfUiDA"
   },
   "source": [
    "### Other Experiments\n",
    "You can experiment with some other search function settings. For example try the following.\n",
    "You should try running it several times:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "QNteBJRbUiDB"
   },
   "outputs": [],
   "source": [
    "search( RS, 'DF/LIFO', 100000, cost=None, loop_check=False, randomise=True )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "wFNjbyY9UiDB"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "name": "SearchExercise3.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
